package com.ruoyi.insect.service.impl;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.insect.service.ICropDiseaseMappingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.insect.mapper.DiseaseLabelMapper;
import com.ruoyi.insect.domain.DiseaseLabel;
import com.ruoyi.insect.service.IDiseaseLabelService;
import com.ruoyi.common.config.RuoYiConfig;

import javax.imageio.ImageIO;

@Service
public class DiseaseLabelServiceImpl implements IDiseaseLabelService {
    // 添加 logger 声明
    private static final Logger logger = LoggerFactory.getLogger(DiseaseLabelServiceImpl.class);
    @Autowired
    private DiseaseLabelMapper diseaseLabelMapper;

    @Autowired
    private ICropDiseaseMappingService cropCategoryService;

    @Override
    public DiseaseLabel selectDiseaseLabelById(Long id) {
        return diseaseLabelMapper.selectDiseaseLabelById(id);
    }

    @Override
    public List<DiseaseLabel> selectDiseaseLabelList(DiseaseLabel diseaseLabel) {
        return diseaseLabelMapper.selectDiseaseLabelList(diseaseLabel);
    }

    @Override
    public int insertDiseaseLabel(DiseaseLabel diseaseLabel) {
        return diseaseLabelMapper.insertDiseaseLabel(diseaseLabel);
    }

    @Override
    public int updateDiseaseLabel(DiseaseLabel diseaseLabel) {
        return diseaseLabelMapper.updateDiseaseLabel(diseaseLabel);
    }

    @Override
    public int deleteDiseaseLabelById(Long id) {
        return diseaseLabelMapper.deleteDiseaseLabelById(id);
    }

    @Override
    public int deleteDiseaseLabelByIds(Long[] ids) {
        return diseaseLabelMapper.deleteDiseaseLabelByIds(ids);
    }

    @Override
    public String processImageUpload(String originalFileName, byte[] fileData, String deviceId, String userName, Double longitude, Double latitude) {
        try {
            // 生成新的文件名 - 严格按照要求的格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
            String timeStamp = sdf.format(new Date());

            // 格式化经纬度，用下划线替换小数点
            String lonStr = "unknown";
            String latStr = "unknown";

            if (longitude != null) {
                lonStr = String.format("%.6f", longitude).replace(".", "_");
            }
            if (latitude != null) {
                latStr = String.format("%.6f", latitude).replace(".", "_");
            }

            // 按照要求格式生成文件名：IMG_{device}_{user}_{lon}_{lat}_{time}.jpg
            String newFileName = String.format("IMG_%s_%s_%s_%s_%s.jpg",
                    deviceId,
                    userName,
                    lonStr,
                    latStr,
                    timeStamp);

            // 获取上传路径
            String uploadDir = RuoYiConfig.getUploadPath();
            Path uploadPath = Paths.get(uploadDir);

            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // 保存文件
            Path filePath = uploadPath.resolve(newFileName);
            Files.write(filePath, fileData);

            return newFileName;

        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }

    /**
     * 生成标注结果图片
     */
    public String generateAnnotatedImage(String originalImage, String annotationData) {
        try {
            logger.info("开始生成标注图片，原图: {}, 标注数据长度: {}", originalImage,
                    annotationData != null ? annotationData.length() : 0);

            // 检查是否有标注数据
            if (annotationData == null || annotationData.isEmpty()) {
                logger.info("没有标注数据，返回原图");
                return originalImage;
            }

            // 解析标注数据
            JSONObject annotationJson = JSON.parseObject(annotationData);
            JSONArray labels = annotationJson.getJSONArray("labels");

            logger.info("解析到标注数量: {}", labels != null ? labels.size() : 0);

            if (labels == null || labels.isEmpty()) {
                logger.info("标注数据为空，返回原图");
                return originalImage;
            }

            // 读取原图
            String uploadDir = RuoYiConfig.getUploadPath();
            Path originalImagePath = Paths.get(uploadDir, originalImage);

            logger.info("原图完整路径: {}", originalImagePath.toAbsolutePath());
            logger.info("原图文件存在: {}", Files.exists(originalImagePath));

            if (!Files.exists(originalImagePath)) {
                logger.error("原图文件不存在: {}", originalImagePath);
                return originalImage;
            }

            BufferedImage image = ImageIO.read(originalImagePath.toFile());

            if (image == null) {
                logger.error("无法读取原图: {}", originalImage);
                return originalImage;
            }

            logger.info("原图尺寸: {}x{}", image.getWidth(), image.getHeight());

            // 创建图形上下文
            Graphics2D g2d = image.createGraphics();

            // 设置绘制属性
            g2d.setStroke(new BasicStroke(3));
            g2d.setFont(new Font("Arial", Font.BOLD, 16));

            // 启用抗锯齿
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // 颜色数组，用于不同标注
            Color[] colors = {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA, Color.CYAN};

            // 绘制每个标注框
            for (int i = 0; i < labels.size(); i++) {
                JSONObject label = labels.getJSONObject(i);
                JSONArray bbox = label.getJSONArray("bbox");
                String category = label.getString("category");

                logger.info("处理第 {} 个标注: {}, bbox: {}", i + 1, category, bbox);

                if (bbox != null && bbox.size() == 4) {
                    // 获取归一化坐标 [x_min, y_min, x_max, y_max]
                    double x_min = bbox.getDouble(0);
                    double y_min = bbox.getDouble(1);
                    double x_max = bbox.getDouble(2);
                    double y_max = bbox.getDouble(3);

                    logger.info("归一化坐标: [{}, {}, {}, {}]", x_min, y_min, x_max, y_max);

                    // 转换为像素坐标
                    int pixelX1 = (int) (x_min * image.getWidth());
                    int pixelY1 = (int) (y_min * image.getHeight());
                    int pixelX2 = (int) (x_max * image.getWidth());
                    int pixelY2 = (int) (y_max * image.getHeight());
                    int width = pixelX2 - pixelX1;
                    int height = pixelY2 - pixelY1;

                    logger.info("像素坐标: [{}, {}, {}, {}]", pixelX1, pixelY1, width, height);

                    // 设置颜色
                    Color color = colors[i % colors.length];
                    g2d.setColor(color);

                    // 绘制矩形框
                    g2d.drawRect(pixelX1, pixelY1, width, height);

                    // 绘制标签背景
                    String labelText = (i + 1) + ": " + category;
                    FontMetrics metrics = g2d.getFontMetrics();
                    int textWidth = metrics.stringWidth(labelText);
                    int textHeight = metrics.getHeight();

                    g2d.setColor(color);
                    g2d.fillRect(pixelX1, pixelY1 - textHeight, textWidth + 8, textHeight);

                    // 绘制标签文字
                    g2d.setColor(Color.WHITE);
                    g2d.drawString(labelText, pixelX1 + 4, pixelY1 - 4);

                    logger.info("成功绘制标注框: {} at [{}, {}, {}, {}]", labelText, pixelX1, pixelY1, width, height);
                }
            }

            g2d.dispose();

            // 生成标注结果图片文件名
            String annotatedFileName = originalImage.replace(".jpg", "_annotated.jpg")
                    .replace(".png", "_annotated.png")
                    .replace(".jpeg", "_annotated.jpeg");

            logger.info("标注结果文件名: {}", annotatedFileName);

            // 保存标注结果图片
            Path annotatedImagePath = Paths.get(uploadDir, annotatedFileName);
            String formatName = originalImage.toLowerCase().endsWith(".png") ? "png" : "jpg";
            boolean writeSuccess = ImageIO.write(image, formatName, annotatedImagePath.toFile());

            if (writeSuccess) {
                logger.info("标注结果图片已生成并保存: {}", annotatedImagePath.toAbsolutePath());
                logger.info("标注图片文件存在: {}", Files.exists(annotatedImagePath));
            } else {
                logger.error("ImageIO.write 返回 false，图片保存失败");
            }

            return annotatedFileName;

        } catch (Exception e) {
            logger.error("生成标注结果图片失败", e);
            return originalImage; // 失败时返回原图
        }
    }

    /**
     * 保存标注数据并生成标注图片
     */
    @Override
    public int updateDiseaseLabelWithAnnotation(DiseaseLabel diseaseLabel) {
        // 如果有标注数据，生成标注结果图片
        if (diseaseLabel.getAnnotationData() != null && !diseaseLabel.getAnnotationData().isEmpty()) {
            try {
                String annotatedImage = generateAnnotatedImage(
                        diseaseLabel.getOriginalImage(),
                        diseaseLabel.getAnnotationData()
                );
                diseaseLabel.setAnnotatedImage(annotatedImage);
            } catch (Exception e) {
                logger.error("生成标注图片失败，但继续保存数据", e);
            }
        }

        return diseaseLabelMapper.updateDiseaseLabel(diseaseLabel);
    }
}
